/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Initial Developer of the Original Code is
*   Nick Kreeger
* Portions created by the Initial Developer are Copyright (C) 2006-2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*   Nick Kreeger <nick.kreeger@park.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */

#include "CHMsgHeaderSink.h"
#import "Attachment.h"

#import "nsIStringEnumerator.h"
#import "nsString.h"
#import "nsIArray.h"
#import "nsIMsgMailNewsUrl.h"

#import "CHMsgService.h"

#import "NSString+Utils.h"

//XXX most of this file is coming from msgHdrViewOverlay.js @ 326.

NS_IMPL_ISUPPORTS1(CHMsgHeaderSink, nsIMsgHeaderSink);

CHMsgHeaderSink::CHMsgHeaderSink(CHMsgService* aMsgService)
: mMsgServiceOwner(aMsgService)
, mSaveHdr(nsnull)
{
  mDummyHeader = nil;
  mCurrentAttachments = [[NSMutableArray alloc] init];
  mCurrentHeaderData = [[NSMutableArray alloc] init];
}

CHMsgHeaderSink::~CHMsgHeaderSink()
{
  if (mDummyHeader)
    [mDummyHeader release]; 
  
  [mCurrentAttachments release];
  [mCurrentHeaderData release];
}

NS_IMETHODIMP
CHMsgHeaderSink::ProcessHeaders(nsIUTF8StringEnumerator* aHeaderNames, 
                                nsIUTF8StringEnumerator* aHeaderValues,
                                PRBool dontCollectAddress)
{
  ClearCurrentHeaders();
  
  //int index = 0;
  PRBool hasMore;
  aHeaderNames->HasMore(&hasMore);
  DummyMessageHeader* newDummyHdr = [[DummyMessageHeader alloc] init];
  while (hasMore)
  {
    // Make these Auto strings so they release
    nsCString curValue;
    nsCString curName;
    aHeaderValues->GetNext(curValue);
    aHeaderNames->GetNext(curName);

    //XXX do I need to use this? It seems to be just  for news groups.
    if (curName.LowerCaseEqualsLiteral("x-mailer") ||
        curName.LowerCaseEqualsLiteral("x-newsreader") ||
        curName.LowerCaseEqualsLiteral("x-mimeole"))
    {
      curName = NS_LITERAL_CSTRING("user-agent");
    }

    if (curName.LowerCaseEqualsLiteral("from"))
      [newDummyHdr setAuthor:[NSString stringWith_nsACString:curValue]]; 
    
    else if (curName.LowerCaseEqualsLiteral("to"))
      [newDummyHdr setTo:[NSString stringWith_nsACString:curValue]];
    
    else if (curName.LowerCaseEqualsLiteral("cc"))
      [newDummyHdr setCc:[NSString stringWith_nsACString:curValue]];
    
    else if (curName.LowerCaseEqualsLiteral("date"))
      [newDummyHdr setDateString:[NSString stringWith_nsACString:curValue]];
    
    else if (curName.LowerCaseEqualsLiteral("subject"))
      [newDummyHdr setSubject:[NSString stringWith_nsACString:curValue]];
    
    else if (curName.LowerCaseEqualsLiteral("reply-to")) { /* Worth saving ? */ }
    
    else if (curName.LowerCaseEqualsLiteral("message-id")) { /* Worth saving ? */ }
    
    // according to RFC 2822, certain headers
    // can occur "unlimited" times.
    //XXX i need to check to see if the lowercase value of the header name exists 
    // in the currentHeaderData[].
    
    //XXX left off at line 383 of msgHdrViewOverlay.js
    
    aHeaderNames->HasMore(&hasMore);
  }
  
  mDummyHeader = newDummyHdr;
  
  return NS_OK;
}

NS_IMETHODIMP 
CHMsgHeaderSink::HandleAttachment(const char* contentType, 
                                  const char* url, 
                                  const PRUnichar* displayName,
                                  const char* uri, 
                                  PRBool aNotDownloaded)
{
  nsresult rv;
  
  /*
   Comment from msgHdrViewOverlay.js:
   "presentation level change....don't show vcards as external attachments in the UI.
    libmime already renders them inline."
   */
  
  if (!mSaveHdr)
  {
    rv = mMsgServiceOwner->MsgHdrFromURI(uri, getter_AddRefs(mSaveHdr));
    if (NS_FAILED(rv))  // not suprising if this fails right now.
      printf("Could not get the msg hdr from the uri: %u\n", rv);
  }
  
  //XXX this isn't the safest alternative, i should find a good XPCOM string class
  //    to use in place of the const char*'s
  if (contentType == "text/x-vcard") 
  {
    /**
     * Check to see if inline attachments should be allowed.
     * Since we aren't supporting inline attachments ATM...
     
     var inlineAttachments = pref.getBoolPref("mail.inline_attachments");
     var displayHtmlAs = pref.getIntPref("mailnews.display.html_as");
     if (inlineAttachments && !displayHtmlAs)
     return;
     */
  }
  
  Attachment* newAttachment = [[Attachment alloc] initWithContentType:[NSString stringWithCString:contentType]
                                                                  url:[NSString stringWithCString:url] 
                                                          displayName:[NSString stringWithPRUnichars:displayName] 
                                                                  uri:[NSString stringWithCString:uri] 
                                                 isExternalAttachment:aNotDownloaded];
  [mCurrentAttachments addObject:newAttachment];
  [newAttachment release];
  
  /*
  CHAttachmentInfo* attachInfo = new CHAttachmentInfo(contentType, url, displayName, uri, aNotDownloaded);
  mCurrentAttachments->AppendElement((nsISupports*)attachInfo, PR_FALSE);

  // Make sure our UI will now that the current message has an attachment.
  PRUint32 numAttachments;
  rv = mCurrentAttachments->GetLength(&numAttachments);
  if (NS_SUCCEEDED(rv) && numAttachments == 1)
  {
    mSaveHdr->MarkHasAttachments(PR_TRUE);
  }
  
  // I'm going to delete the pointer now, this might be a problem if the nsIMutableArray doesn't own the item
  // like I think it does.
  delete attachInfo;
   */
  
  return NS_OK;
}

NS_IMETHODIMP
CHMsgHeaderSink::OnEndAllAttachments()
{
  mMsgServiceOwner->OnEndAttachments(mCurrentAttachments);
  
  return NS_OK;
}

NS_IMETHODIMP 
CHMsgHeaderSink::OnEndMsgHeaders(nsIMsgMailNewsUrl* aUrl)
{
  mMsgServiceOwner->OnMsgLoaded(aUrl, mDummyHeader);
  
  return NS_OK;
}

NS_IMETHODIMP
CHMsgHeaderSink::OnEndMsgDownload(nsIMsgMailNewsUrl* aUrl)
{
  nsresult rv;
  
  // If we did not find any attachments, turn off the attachments flag
  if (!mSaveHdr)
  {
    nsCOMPtr<nsIMsgMessageUrl> messageUrl(do_QueryInterface(aUrl, &rv));
    if (NS_SUCCEEDED(rv))
    {
      nsXPIDLCString uri;
      rv = messageUrl->GetUri(getter_Copies(uri));
      if (NS_SUCCEEDED(rv))
      {
        rv = mMsgServiceOwner->MsgHdrFromURI(uri, getter_AddRefs(mSaveHdr));
      }
    }
  }
  
  /*
  PRUint32 numAttachments;
  rv = mCurrentAttachments->GetLength(&numAttachments);
  if (numAttachments == 0 && mSaveHdr)
    mSaveHdr->MarkHasAttachments(PR_FALSE);
   */
  
  return NS_OK;
}

NS_IMETHODIMP
CHMsgHeaderSink::GetSecurityInfo(nsISupports** aSecurityInfo)
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP 
CHMsgHeaderSink::SetSecurityInfo(nsISupports* aSecurityInfo)
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP 
CHMsgHeaderSink::OnMsgHasRemoteContent(nsIMsgDBHdr* aMsgHdr)
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP 
CHMsgHeaderSink::GetDummyMsgHeader(nsIMsgDBHdr** aRetval)
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
CHMsgHeaderSink::GetProperties(nsIWritablePropertyBag2 * *aProperties)
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

void 
CHMsgHeaderSink::ClearCurrentHeaders()
{
  [mCurrentAttachments removeAllObjects];
  [mCurrentHeaderData removeAllObjects];
  if (mDummyHeader)
    [mDummyHeader release];
}

DummyMessageHeader* 
CHMsgHeaderSink::GetDummyMessageHeader()
{
  return mDummyHeader;
}
